package com.et.machine.manager.vm.goods

import android.os.Environment
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.recyclerview.widget.DiffUtil
import com.et.logger.ELog
import com.et.logger.TAGS
import com.et.machine.BuildConfig
import com.et.machine.convert.machineIdInfo
import com.et.machine.convert.machineInfo
import com.et.machine.manager.vm.goods.GoodsFragment.Companion
import com.et.machine.manager.vm.goods.GoodsFragment.Companion.BOX_01
import com.et.machine.manager.vm.goods.GoodsFragment.Companion.BOX_02
import com.et.machine.manager.vm.goods.GoodsFragment.Companion.BOX_03
import com.et.machine.manager.vm.goods.GoodsFragment.Companion.BOX_04
import com.et.machine.manager.vm.goods.GoodsFragment.Companion.BOX_05
import com.et.machine.manager.vm.goods.GoodsFragment.Companion.BOX_06
import com.et.machine.manager.vm.goods.GoodsFragment.Companion.BOX_07
import com.et.machine.manager.vm.goods.GoodsFragment.Companion.BOX_08
import com.et.machine.manager.vm.goods.GoodsFragment.Companion.BOX_09
import com.et.machine.manager.vm.goods.GoodsFragment.Companion.BOX_11
import com.et.machine.store.ChannelEntity
import com.et.machine.util.HttpUse
import com.et.machine.util.LabelChannel
import com.et.machine.util.Result
import com.et.util.download
import com.et.util.getFileExtensionFromUrl
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.net.SocketTimeoutException
import kotlin.math.ceil

const val QUERY_GOODS_BY_BARCODE_MVV = BuildConfig.query_goods_by_barcode

@Suppress("NAME_SHADOWING", "DEPRECATION")
class GoodsViewModel : ViewModel() {

    private var poster: HttpUse.Post? = null
    private val foodNumber =
        (machineInfo?.nFood!!) +
                (machineIdInfo?.nFood2!!) +
                (machineIdInfo?.nFood3!!) +
                (machineIdInfo?.nFood4!!)

    suspend fun goodsFromNet(): Result = withContext(Dispatchers.IO) {
        val uuid = machineInfo?.uuid ?: return@withContext Result(false, 0, "machine not ready")
        return@withContext Result().apply {
            HttpUse.Post(r = this).putUrl(QUERY_GOODS_BY_BARCODE_MVV)
                .putParam(HashMap<String, String>().apply { put("avm", uuid) }).base64(false)
                .build().apply {
                    poster = this
                    execute()
                }
        }
    }

    fun disposable() {
        poster?.cancel()
        poster = null
    }


    /**
     * box box count
     */
    fun addBoxList(): MutableList<Companion.Box> {
        val boxData = mutableListOf<Companion.Box>()
        Log.d(
            "MachineIdInfo", "nFood:${machineInfo?.nFood!!}, " +
                    "nFood2:${(machineIdInfo?.nFood2!!)}, " +
                    "nFood3:${(machineIdInfo?.nFood3!!)}, " +
                    "nFood4:${(machineIdInfo?.nFood4!!)}"
        )

        if (machineInfo?.cDrink!! > 0) {
            boxData.add(Companion.Box(false, BOX_11))
        }
        for (i in 9 downTo 10 - ceil(foodNumber / 48.0).toInt()) {
            boxData.add(Companion.Box(false, i))
        }
        for (i in 1..(machineInfo?.cBox!!)) {
            boxData.add(Companion.Box(false, i))
        }

        return boxData
    }


    fun box2Name(id: Int): String {
        return when (id) {
            BOX_11 -> "$id 饮料机"
            BOX_06, BOX_07, BOX_08, BOX_09 -> "$id 食品机"
            BOX_01, BOX_02, BOX_03, BOX_04, BOX_05 -> "$id 格子柜"
            else -> "unknown"
        }
    }

    /**
     * channel label
     */
    fun getChannelLabel(box: Int, channel: Int): String {
        val ins = LabelChannel.getInstance()
        ins.apply {
            initFoodChannelCount(9, machineInfo?.nFood ?: 0)
            initFoodChannelCount(8, machineIdInfo?.nFood2 ?: 0)
            initFoodChannelCount(7, machineIdInfo?.nFood3 ?: 0)
            initFoodChannelCount(6, machineIdInfo?.nFood4 ?: 0)
        }
        return ins.channelLabel(box, channel)
    }


    fun downloadImage(
        channelEntity: ChannelEntity,
        company: String,
        listener: OnDownloadListener
    ) {
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
            .also { picture ->
                if (!picture.exists()) picture.mkdir()
                if (picture.exists() && picture.isDirectory) {
                    val ext = (channelEntity.image).getFileExtensionFromUrl()
                    File(picture, "${channelEntity.name}.$ext").apply {
                        if (exists()) {
                            listener.back(absolutePath)
                            return@also
                        }
                        GlobalScope.launch(Dispatchers.IO) {
                            try {
                                download("${BuildConfig.picUri}$company/${channelEntity.image}") { f ->
                                    if (f < 0) {
                                        ELog.d(
                                            TAGS.vending,
                                            "vending:download image failed>>${channelEntity.name}.$ext}"
                                        )
                                    } else if (f == 1f) {
                                        GlobalScope.launch(Dispatchers.Main) {
                                            listener.back(absolutePath)
                                        }
                                        ELog.d(
                                            TAGS.vending,
                                            "vending:download image finish>>${channelEntity.name}.$ext}"
                                        )
                                    }
                                }
                            } catch (e: SocketTimeoutException) {
                                listener.back(channelEntity.image)
                                ELog.d(
                                    TAGS.vending,
                                    "vending:download image Timeout!!>>${channelEntity.name}.$ext}"
                                )
                            }
                        }
                    }
                }
            }
    }

    interface OnDownloadListener {
        fun back(path: String)
    }

}


class GoodsDiffCallBack(
    private val src: MutableList<ChannelEntity>,
    private val dest: MutableList<ChannelEntity>
) :
    DiffUtil.Callback() {
    override fun getOldListSize(): Int = src.size

    override fun getNewListSize(): Int = dest.size

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return true
    }

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return false
    }

}